package com.citycloud.ccuap.tc.oauth2.controller;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerEndpointsConfiguration;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.OAuth2Request;
import org.springframework.security.oauth2.provider.TokenRequest;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;
import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.citycloud.ccuap.commons.application.Application;
import com.citycloud.ccuap.commons.json.JSONData;
import com.citycloud.ccuap.commons.sys.entity.SysParameter;
import com.citycloud.ccuap.tc.common.dto.DataCSecurityBasicUser;
import com.citycloud.ccuap.tc.common.result.ResultObject;
import com.citycloud.ccuap.tc.oauth2.config.CustomerProperties;
import com.citycloud.ccuap.tc.oauth2.dto.DetailedUserInfo;
import com.citycloud.ccuap.tc.oauth2.dto.UserInfoForSwitchSite;
import com.citycloud.ccuap.tc.oauth2.dto.UserInfoSites;
import com.citycloud.ccuap.tc.oauth2.feignclient.SysFCService;
import com.citycloud.ccuap.tc.oauth2.service.SiteService;
import com.citycloud.ccuap.tc.oauth2.service.UserService;

import io.swagger.annotations.ApiOperation;
import lombok.extern.log4j.Log4j2;

@Log4j2
@RestController
public class NonSessionBasedSiteController {


    @Autowired
    private ClientDetailsService clientDetailsService;

    @Qualifier("defaultAuthorizationServerTokenServices")
    @Autowired
    private AuthorizationServerTokenServices authorizationServerTokenServices;

    @Autowired
    private AuthorizationServerEndpointsConfiguration endpoints;

    @Autowired
    private SiteService siteService;

    @Autowired
    private UserService userService;
    
    @Autowired
    private DataSource dataSource;
    
    @RequestMapping(
            value = {"/nonSessionBased/logout"},
            method = {RequestMethod.GET, RequestMethod.POST}
    )
    public ResultObject<OAuth2AccessToken> logout(@RequestParam("token") String value) {
        ResourceServerTokenServices resourceServerTokenServices = endpoints.getEndpointsConfigurer().getResourceServerTokenServices();
        //检测用户token是否有效
        OAuth2AccessToken token = resourceServerTokenServices.readAccessToken(value);
        if (token == null) {
            return ResultObject.getInstance().error(new InvalidTokenException("Token was not recognised"));
        } else if (token.isExpired()) {
            return ResultObject.getInstance().error(new InvalidTokenException("Token has expired"));
        } else {
            //获取用户ID
            OAuth2Authentication authentication = resourceServerTokenServices.loadAuthentication(token.getValue());

            if (authentication.getUserAuthentication() == null) {
                return ResultObject.getInstance().error("该token(" + value + ")属于由客户端授权模式获取的token，不包含用户信息");
            }

            String username = ((DataCSecurityBasicUser) authentication.getUserAuthentication().getPrincipal()).getUsername();
            // TODO 此处优化
            JdbcTokenStore tokenStore = new JdbcTokenStore(dataSource);
            if (tokenStore instanceof JdbcTokenStore) {
                JdbcTokenStore jdbcTokenStore = (JdbcTokenStore) tokenStore;
                Collection<OAuth2AccessToken> oAuth2AccessTokenList = jdbcTokenStore.findTokensByUserName(String.valueOf(username));
                Iterator<OAuth2AccessToken> oAuth2AccessToken = oAuth2AccessTokenList.iterator();
                while (oAuth2AccessToken.hasNext()) {
                    jdbcTokenStore.removeAccessToken(oAuth2AccessToken.next());
                }
            }
        }

        Map<String, String> data = new HashMap<>();
        data.put("loginPage", CustomerProperties.authenticationFrontendUrl);
        data.put("loginUrl", CustomerProperties.authenticationBackendUrl + "/login");
        return ResultObject.getInstance().success("操作成功", data);
    }



    @RequestMapping(
            value = {"/user/getUserInfo"},
            method = {RequestMethod.GET, RequestMethod.POST}
    )
    public ResultObject<DetailedUserInfo> getUserInfo(@RequestParam("token") String value) {

        ResourceServerTokenServices resourceServerTokenServices = endpoints.getEndpointsConfigurer().getResourceServerTokenServices();

        //检测用户token是否有效
        OAuth2AccessToken token = resourceServerTokenServices.readAccessToken(value);
        if (token == null) {
            return ResultObject.getInstance().error(new InvalidTokenException("Token was not recognised"));
        } else if (token.isExpired()) {
            return ResultObject.getInstance().error(new InvalidTokenException("Token has expired"));
        } else {
            //获取用户ID
            OAuth2Authentication authentication = resourceServerTokenServices.loadAuthentication(token.getValue());

            if (authentication.getUserAuthentication() == null) {
                return ResultObject.getInstance().error("该token(" + value + ")属于由客户端授权模式获取的token，不包含用户信息");
            }

            Long userId = ((DataCSecurityBasicUser) authentication.getUserAuthentication().getPrincipal()).getUserId();

            DetailedUserInfo user = new DetailedUserInfo();
            user.setUserId(userId);

            Set<String> scopes = authentication.getOAuth2Request().getScope();
            // 用户当前所在站点有且只有一个, 其它都是由于用户申请token时传参不规范导致的错误数据
            if (scopes != null && scopes.size() == 1) {
                try {
                    user.setCurrentSiteId(Long.parseLong(scopes.iterator().next()));
                } catch (NumberFormatException e) {
                    log.error("无效的当前站点ID! 应该是Long型", e);
                }
            }
            if (!CustomerProperties.authorizationProjectId.equals(0L)) {
                user.setPlatformId(CustomerProperties.authorizationProjectId);
            }

            DetailedUserInfo result = userService.getDetailedUserInfo(user);
            if (result == null) {
                return ResultObject.getInstance().error("获取用户信息 (user id: " + userId + ")失败，请联系管理员");
            } else {
                return ResultObject.getInstance().success("获取用户信息成功", userService.getDetailedUserInfo(user));
            }
        }
    }

    /**获取用户可以切换的站点列表*/
    @RequestMapping(
            value = {"/nonSessionBased/siteList"},
            method = {RequestMethod.GET, RequestMethod.POST}
    )
    public @ResponseBody
    ResultObject<UserInfoSites> getSwitchSiteList(@RequestParam("token") String value) {
        ResourceServerTokenServices resourceServerTokenServices = endpoints.getEndpointsConfigurer().getResourceServerTokenServices();

        //检测用户token是否有效
        OAuth2AccessToken token = resourceServerTokenServices.readAccessToken(value);
        if (token == null) {
            return ResultObject.getInstance().error(new InvalidTokenException("Token was not recognised"));
        } else if (token.isExpired()) {
            return ResultObject.getInstance().error(new InvalidTokenException("Token has expired"));
        } else {
            //获取用户ID
            OAuth2Authentication authentication = resourceServerTokenServices.loadAuthentication(token.getValue());
            DataCSecurityBasicUser user = (DataCSecurityBasicUser) authentication.getUserAuthentication().getPrincipal();
            Assert.notNull(user,"当前用户信息不能为空！");
            //获取用户以及站点类型列表
            UserInfoSites userInfoSites = siteService.getSwitchSiteList(user.getUserId(),null,null);
            UserInfoForSwitchSite userInfoForSwitchSite = new UserInfoForSwitchSite(user);
            if(userInfoSites.getUserInfo() != null && userInfoSites.getUserInfo().getPlatformSite() != null){
                userInfoForSwitchSite.setPlatformSite(userInfoSites.getUserInfo().getPlatformSite());
            }
            userInfoSites.setUserInfo(userInfoForSwitchSite);
            return ResultObject.getInstance().success("获取用户站点列表成功", userInfoSites);
        }
    }

    /**用于手机APP端切换站点*/
    @RequestMapping(
            value = {"/nonSessionBased/switchSite"},
            method = {RequestMethod.GET, RequestMethod.POST}
    )
    public ResultObject<OAuth2AccessToken> switchSite(@RequestParam("siteId") String scope, @RequestParam("token") String value) {

        ResourceServerTokenServices resourceServerTokenServices = endpoints.getEndpointsConfigurer().getResourceServerTokenServices();
        AuthorizationServerTokenServices customTokenServices = endpoints.getEndpointsConfigurer().getTokenServices();
        //检测用户token是否有效
        OAuth2AccessToken token = resourceServerTokenServices.readAccessToken(value);
        if (token == null) {
            return ResultObject.getInstance().error(new InvalidTokenException("Token was not recognised"));
        } else if (token.isExpired()) {
            return ResultObject.getInstance().error(new InvalidTokenException("Token has expired"));
        } else {

            //通过SiteID 获取 ClientID

            String clientId = siteService.getClientIdBySiteId(Long.parseLong(scope));
            if (clientId == null) {
                return ResultObject.getInstance().error("错误的站点ID：" + scope + "，请联系平台管理员");
            }

            /*为用户颁发转跳目标站点的 new token*/
            OAuth2Authentication authentication = resourceServerTokenServices.loadAuthentication(token.getValue());
            ClientDetails authenticatedClient = clientDetailsService.loadClientByClientId(clientId);
            Set<String> scopes = new HashSet<>(2);
            scopes.add(scope);
            TokenRequest tokenRequest = new TokenRequest(new HashMap<String, String>(), clientId, scopes, "custom");
            OAuth2Request oAuth2Request = tokenRequest.createOAuth2Request(authenticatedClient);
            OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(oAuth2Request, authentication);
//            OAuth2AccessToken newToken = authorizationServerTokenServices.createAccessToken(oAuth2Authentication);
            OAuth2AccessToken newToken = customTokenServices.createAccessToken(oAuth2Authentication);
            return ResultObject.getInstance().success("切换站点成功", newToken);
        }
    }
    
    @ApiOperation("根据条件查询对象")
	@RequestMapping(value = "/nonSessionBased/getParameterList", method = { RequestMethod.GET, RequestMethod.POST })
	public JSONData<List<SysParameter>> getParameterList() throws Exception {
    	SysFCService fcService = Application.getClassBean(SysFCService.class);
		JSONData<List<SysParameter>> jsonData = fcService.getParameterList();
		return jsonData;
	}

}
